<template>
  <div>
    <div class="flowup">
      <el-form :model="form" label-width="300px" @submit.prevent="submitForm">
        <el-form-item label="Datapath ID (dpid) 数据路径ID">
          <el-input v-model.number="form.dpid" placeholder="Datapath ID" required></el-input>
        </el-form-item>
        <el-form-item label="Cookie">
          <el-input v-model.number="form.cookie" placeholder="Cookie"></el-input>
        </el-form-item>
        <el-form-item label="Cookie Mask Cookie掩码">
          <el-input v-model.number="form.cookie_mask" placeholder="Cookie Mask"></el-input>
        </el-form-item>
        <el-form-item label="Table ID 表ID">
          <el-input v-model.number="form.table_id" placeholder="Table ID"></el-input>
        </el-form-item>
        <el-form-item label="Idle Timeout (seconds) 空闲超时时间 (秒)">
          <el-input v-model.number="form.idle_timeout" placeholder="Idle Timeout"></el-input>
        </el-form-item>
        <el-form-item label="Hard Timeout (seconds) 硬超时时间 (秒)">
          <el-input v-model.number="form.hard_timeout" placeholder="Hard Timeout"></el-input>
        </el-form-item>
        <el-form-item label="Priority 优先级">
          <el-input v-model.number="form.priority" placeholder="Priority" required></el-input>
        </el-form-item>
        <el-form-item label="Flags 标志">
          <el-input v-model.number="form.flags" placeholder="Flags"></el-input>
        </el-form-item>
        <el-form-item label="Match In Port 匹配入口端口">
          <el-input v-model.number="form.match_in_port" placeholder="Match In Port" required></el-input>
        </el-form-item>
        <el-form-item label="Instruction Type 指令类型">
          <el-select v-model="form.instruction_type" placeholder="请选择">
            <el-option label="APPLY_ACTIONS 应用动作" value="APPLY_ACTIONS"></el-option>
            <el-option label="GOTO_TABLE 跳转到表" value="GOTO_TABLE"></el-option>
            <el-option label="WRITE_METADATA 写入元数据" value="WRITE_METADATA"></el-option>
            <el-option label="METER 应用计量器" value="METER"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="Instruction Details 指令详情" v-if="form.instruction_type === 'APPLY_ACTIONS'">
          <el-input v-model="form.action_details" placeholder="Action Details, e.g., {'max_len': 65535, 'port': 2, 'type': 'OUTPUT'}"></el-input>
        </el-form-item>
        <el-form-item label="Instruction Details 指令详情" v-if="form.instruction_type === 'GOTO_TABLE'">
          <el-input v-model="form.goto_table_id" placeholder="Table ID"></el-input>
        </el-form-item>
        <el-form-item label="Instruction Details 指令详情" v-if="form.instruction_type === 'WRITE_METADATA'">
          <el-input v-model="form.metadata" placeholder="Metadata"></el-input>
          <el-input v-model="form.metadata_mask" placeholder="Metadata Mask"></el-input>
        </el-form-item>
        <el-form-item label="Instruction Details 指令详情" v-if="form.instruction_type === 'METER'">
          <el-input v-model="form.meter_id" placeholder="Meter ID"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm">Submit 提交</el-button>
          
        </el-form-item>
        
      </el-form>
    </div>
    <el-dialog
  title="区块链操作信息"
  :visible.sync="dialogVisible"
  width="35%">
  <div v-if="latestOperation">
    <p>合约地址：{{ latestOperation.contractAddress }}</p>
    <p>操作者：{{ latestOperation.operator }}</p>
    <p>交易哈希：{{ latestOperation.blockHash }}</p>
    <p>时间：{{ new Date(latestOperation.timestamp).toLocaleString() }}</p>
  </div>
</el-dialog>
  </div>
</template>
<script>
import Web3 from 'web3';
import axios from 'axios';

export default {
  data() {
    return {
      storageKey: 'blockchain_operations', // 本地存储键名
      dialogVisible: false,
      form: {
      dpid: 1,  // 默认dpid
      cookie: 0,
      cookie_mask: 0,
      table_id: 0,
      idle_timeout: 0,
      hard_timeout: 0,
      priority: 1000,  // 默认优先级
      flags: 0,
      match_in_port: 1,  // 默认入口端口
      instruction_type: 'APPLY_ACTIONS',
      action_details: '{"type":"OUTPUT","port":1,"max_len":65535}', // 默认动作
      goto_table_id: '',
      metadata: '',
      metadata_mask: '',
      meter_id: ''
    },
      newData: '', // 用户输入的新数据
      traceId: null, // 用户输入的查询ID
      traceData: null, // 查询到的数据
      errorMessage: '', // 错误消息
      web3: null, // Web3 实例
      contract: null, // 合约实例
      contractAddress: '0x22A95c9Af71d985021dddea59DCdC7dD1749A60f', // 合约地址
      abi: [ // 合约ABI
        {
          "inputs": [],
          "stateMutability": "nonpayable",
          "type": "constructor"
        },
        {
          "anonymous": false,
          "inputs": [
            {
              "indexed": true,
              "internalType": "uint256",
              "name": "id",
              "type": "uint256"
            },
            {
              "indexed": false,
              "internalType": "string",
              "name": "data",
              "type": "string"
            },
            {
              "indexed": false,
              "internalType": "uint256",
              "name": "timestamp",
              "type": "uint256"
            }
          ],
          "name": "TraceAdded",
          "type": "event"
        },
        {
          "inputs": [],
          "name": "traceCount",
          "outputs": [
            {
              "internalType": "uint256",
              "name": "",
              "type": "uint256"
            }
          ],
          "stateMutability": "view",
          "type": "function",
          "constant": true
        },
        {
          "inputs": [
            {
              "internalType": "uint256",
              "name": "",
              "type": "uint256"
            }
          ],
          "name": "traces",
          "outputs": [
            {
              "internalType": "string",
              "name": "data",
              "type": "string"
            },
            {
              "internalType": "uint256",
              "name": "timestamp",
              "type": "uint256"
            }
          ],
          "stateMutability": "view",
          "type": "function",
          "constant": true
        },
        {
          "inputs": [
            {
              "internalType": "string",
              "name": "_data",
              "type": "string"
            }
          ],
          "name": "addTrace",
          "outputs": [],
          "stateMutability": "nonpayable",
          "type": "function"
        },
        {
          "inputs": [
            {
              "internalType": "uint256",
              "name": "_id",
              "type": "uint256"
            }
          ],
          "name": "getTrace",
          "outputs": [
            {
              "internalType": "string",
              "name": "",
              "type": "string"
            },
            {
              "internalType": "uint256",
              "name": "",
              "type": "uint256"
            }
          ],
          "stateMutability": "view",
          "type": "function",
          "constant": true
        }
      ]
    };
  },
  async mounted() {
    await this.initWeb3(); // 初始化Web3
    await this.initContract(); // 初始化合约
    const savedData = localStorage.getItem(this.storageKey);
    if (savedData) {
      try {
        this.operationHistory = JSON.parse(savedData);
      } catch (e) {
        console.error('解析本地存储数据失败:', e);
      }
    }
  },
  methods: {
    showDialog() {
    this.dialogVisible = true;
  },
    async initWeb3() {
      if (window.ethereum) {
        this.web3 = new Web3(window.ethereum); // 使用MetaMask提供的Web3实例
        try {
          await window.ethereum.enable(); // 请求用户授权访问账户
        } catch (error) {
          console.error("User denied account access", error); // 用户拒绝访问账户
        }
      } else if (window.web3) {
        this.web3 = new Web3(window.web3.currentProvider); // 使用已存在的Web3实例
      } else {
        console.error("No Metamask detected"); // 没有检测到MetaMask
      }
    },
    async initContract() {
      if (this.web3) {
        this.contract = new this.web3.eth.Contract(this.abi, this.contractAddress); // 创建合约实例
      }
    },
    async addTrace(newData) {
      if (this.contract) {
        try {
          const accounts = await this.web3.eth.getAccounts(); // 获取当前账户
          const receipt = await this.contract.methods.addTrace(newData).send({ from: accounts[0] }); // 调用合约方法添加数据

          // 从事件日志中获取 traceId
          const traceId = receipt.events.TraceAdded.returnValues.id;
          console.log("Trace added with ID:", traceId);

          // 获取并打印区块哈希值
          console.log("Block Hash:", receipt.blockHash);

          this.newData = ''; // 清空输入框

          const operationData = {
            timestamp: new Date().toISOString(),
            contractAddress: this.contractAddress,
            operator: 'admin',
            traceId: traceId,
            blockHash: receipt.blockHash
          };
          
          // 读取已有数据并追加新记录
          const history = JSON.parse(localStorage.getItem(this.storageKey) || '[]');
          history.push(operationData);
          localStorage.setItem(this.storageKey, JSON.stringify(history));

        } catch (error) {
          console.error("Error adding trace:", error); // 捕获并打印错误
          this.errorMessage = "Error adding trace: " + error.message;
        }
      }
    },
    async getTrace() {
      if (this.contract && this.traceId !== null) {
        try {
          const result = await this.contract.methods.getTrace(this.traceId).call(); // 调用合约方法查询数据
          console.log(result);

          // 确保 result 是一个对象并且包含 data 和 timestamp
          if (result && result[0] && result[1]) {
            this.traceData = { data: result[0], timestamp: result[1] }; // 更新查询结果
          } else {
            console.error("Unexpected result format:", result);
            this.errorMessage = "Unexpected result format: " + JSON.stringify(result);
          }
        } catch (error) {
          console.error("Error getting trace:", error); // 捕获并打印错误
          this.errorMessage = "Error getting trace: " + error.message;
        }
      }
    },
    async submitForm() {
      let flowEntry = {
    dpid: Number(this.form.dpid),
    cookie: Number(this.form.cookie),
    cookie_mask: Number(this.form.cookie_mask),
    table_id: Number(this.form.table_id),
    idle_timeout: Number(this.form.idle_timeout),
    hard_timeout: Number(this.form.hard_timeout),
    priority: Number(this.form.priority),
    flags: Number(this.form.flags),
    match: {
      in_port: Number(this.form.match_in_port),
      eth_type: 0x0800  // 固定匹配IPv4
    },
    instructions: []
  };

      if (this.form.instruction_type === 'APPLY_ACTIONS') {
        const actionDetails = JSON.parse(this.form.action_details);
        flowEntry.instructions.push({
          type: 'APPLY_ACTIONS',
          actions: [actionDetails]
        });
      } else if (this.form.instruction_type === 'GOTO_TABLE') {
        flowEntry.instructions.push({
          type: 'GOTO_TABLE',
          table_id: parseInt(this.form.goto_table_id)
        });
      } else if (this.form.instruction_type === 'WRITE_METADATA') {
        flowEntry.instructions.push({
          type: 'WRITE_METADATA',
          metadata: parseInt(this.form.metadata),
          metadata_mask: parseInt(this.form.metadata_mask)
        });
      } else if (this.form.instruction_type === 'METER') {
        flowEntry.instructions.push({
          type: 'METER',
          meter_id: parseInt(this.form.meter_id)
        });
      }

      try {
    const response = await axios.post('/ryu/stats/flowentry/add', flowEntry, {  // 修正API路径
      headers: {'Content-Type': 'application/json'}
    });
    
    // 根据Ryu实际返回结构调整判断逻辑
    if (response.status === 200) {  // 成功状态码
      this.$message.success('流表添加成功!');
      this.addTrace(JSON.stringify(flowEntry));
    } else {
      this.$message.error('添加失败: ' + (response.data.error || '未知错误'));
    }
  } catch (error) {
    // 增强错误处理
    const errorMsg = error.response?.data?.error 
      || error.response?.data?.details 
      || error.message;
    this.$message.error('提交错误: ' + errorMsg);
  }
    }
  }
};
</script>

<style scoped>

  .flowup{
    width: 70%;
    margin: 0px auto;
    margin-top: 50px;
  }
</style>